@affanhamid/markdown-renderer 2.4.0 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -127
- package/dist/index.d.cts +1 -27
- package/dist/index.d.ts +1 -27
- package/dist/index.js +2 -125
- package/package.json +5 -1
package/dist/index.cjs
CHANGED
|
@@ -33,8 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
MATH_MARKDOWN_RULES_APPENDIX: () => MATH_MARKDOWN_RULES_APPENDIX,
|
|
34
34
|
MarkdownRenderer: () => markdown_renderer_default,
|
|
35
35
|
normalizeMathMarkdownDelimiters: () => normalizeMathMarkdownDelimiters,
|
|
36
|
-
renderMarkdownToHtml: () => renderMarkdownToHtml
|
|
37
|
-
tiptapJsonToMarkdown: () => tiptapJsonToMarkdown
|
|
36
|
+
renderMarkdownToHtml: () => renderMarkdownToHtml
|
|
38
37
|
});
|
|
39
38
|
module.exports = __toCommonJS(index_exports);
|
|
40
39
|
|
|
@@ -934,7 +933,7 @@ function renderMarkdownToHtml(markdown, options) {
|
|
|
934
933
|
parts.push(`<p>${content}</p>`);
|
|
935
934
|
i++;
|
|
936
935
|
}
|
|
937
|
-
return `<div class="prose max-w-none">${parts.join("")}</div>`;
|
|
936
|
+
return `<style>.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before,.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after{content:none}</style><div class="prose max-w-none">${parts.join("")}</div>`;
|
|
938
937
|
}
|
|
939
938
|
var mermaidInstance = null;
|
|
940
939
|
var MarkdownRenderer = ({
|
|
@@ -1141,133 +1140,10 @@ var MarkdownRenderer = ({
|
|
|
1141
1140
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: containerRef, className, dangerouslySetInnerHTML: { __html: html } });
|
|
1142
1141
|
};
|
|
1143
1142
|
var markdown_renderer_default = MarkdownRenderer;
|
|
1144
|
-
|
|
1145
|
-
// src/tiptap-to-markdown.ts
|
|
1146
|
-
function renderMarks(text, marks) {
|
|
1147
|
-
if (!marks || marks.length === 0) return text;
|
|
1148
|
-
let result = text;
|
|
1149
|
-
for (const mark of marks) {
|
|
1150
|
-
switch (mark.type) {
|
|
1151
|
-
case "bold":
|
|
1152
|
-
result = `**${result}**`;
|
|
1153
|
-
break;
|
|
1154
|
-
case "italic":
|
|
1155
|
-
result = `*${result}*`;
|
|
1156
|
-
break;
|
|
1157
|
-
case "strike":
|
|
1158
|
-
result = `~~${result}~~`;
|
|
1159
|
-
break;
|
|
1160
|
-
case "code":
|
|
1161
|
-
result = `\`${result}\``;
|
|
1162
|
-
break;
|
|
1163
|
-
case "link": {
|
|
1164
|
-
const href = mark.attrs?.href ?? "";
|
|
1165
|
-
result = `[${result}](${href})`;
|
|
1166
|
-
break;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
return result;
|
|
1171
|
-
}
|
|
1172
|
-
function renderInlineContent(nodes) {
|
|
1173
|
-
if (!nodes) return "";
|
|
1174
|
-
return nodes.map((node) => {
|
|
1175
|
-
if (node.type === "text") {
|
|
1176
|
-
return renderMarks(node.text ?? "", node.marks);
|
|
1177
|
-
}
|
|
1178
|
-
if (node.type === "hardBreak") {
|
|
1179
|
-
return " \n";
|
|
1180
|
-
}
|
|
1181
|
-
if (node.type === "image") {
|
|
1182
|
-
const src = node.attrs?.src ?? "";
|
|
1183
|
-
const alt = node.attrs?.alt ?? "";
|
|
1184
|
-
return ``;
|
|
1185
|
-
}
|
|
1186
|
-
return "";
|
|
1187
|
-
}).join("");
|
|
1188
|
-
}
|
|
1189
|
-
function renderNode(node, indent = "", listCounter) {
|
|
1190
|
-
switch (node.type) {
|
|
1191
|
-
case "doc":
|
|
1192
|
-
return renderChildren(node.content, indent);
|
|
1193
|
-
case "paragraph":
|
|
1194
|
-
return `${indent}${renderInlineContent(node.content)}`;
|
|
1195
|
-
case "heading": {
|
|
1196
|
-
const level = node.attrs?.level ?? 1;
|
|
1197
|
-
const prefix = "#".repeat(level);
|
|
1198
|
-
return `${prefix} ${renderInlineContent(node.content)}`;
|
|
1199
|
-
}
|
|
1200
|
-
case "bulletList":
|
|
1201
|
-
return (node.content ?? []).map((item) => renderNode(item, indent, void 0)).join("\n");
|
|
1202
|
-
case "orderedList": {
|
|
1203
|
-
const counter = { n: node.attrs?.start ?? 1 };
|
|
1204
|
-
return (node.content ?? []).map((item) => {
|
|
1205
|
-
const result = renderNode(item, indent, counter);
|
|
1206
|
-
counter.n++;
|
|
1207
|
-
return result;
|
|
1208
|
-
}).join("\n");
|
|
1209
|
-
}
|
|
1210
|
-
case "listItem": {
|
|
1211
|
-
const prefix = listCounter ? `${indent}${listCounter.n}. ` : `${indent}- `;
|
|
1212
|
-
const children = node.content ?? [];
|
|
1213
|
-
const parts = [];
|
|
1214
|
-
for (let i = 0; i < children.length; i++) {
|
|
1215
|
-
const child = children[i];
|
|
1216
|
-
if (i === 0 && child.type === "paragraph") {
|
|
1217
|
-
parts.push(`${prefix}${renderInlineContent(child.content)}`);
|
|
1218
|
-
} else if (child.type === "bulletList" || child.type === "orderedList") {
|
|
1219
|
-
parts.push(renderNode(child, indent + " "));
|
|
1220
|
-
} else if (child.type === "paragraph") {
|
|
1221
|
-
parts.push(`${indent} ${renderInlineContent(child.content)}`);
|
|
1222
|
-
} else {
|
|
1223
|
-
parts.push(renderNode(child, indent + " "));
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
return parts.join("\n");
|
|
1227
|
-
}
|
|
1228
|
-
case "blockquote":
|
|
1229
|
-
return (node.content ?? []).map((child) => {
|
|
1230
|
-
const line = renderNode(child, indent);
|
|
1231
|
-
return `${indent}> ${line.replace(new RegExp(`^${indent}`), "")}`;
|
|
1232
|
-
}).join("\n");
|
|
1233
|
-
case "codeBlock": {
|
|
1234
|
-
const lang = node.attrs?.language ?? "";
|
|
1235
|
-
const code = (node.content ?? []).map((c) => c.text ?? "").join("");
|
|
1236
|
-
return `${indent}\`\`\`${lang}
|
|
1237
|
-
${code}
|
|
1238
|
-
${indent}\`\`\``;
|
|
1239
|
-
}
|
|
1240
|
-
case "horizontalRule":
|
|
1241
|
-
return `${indent}---`;
|
|
1242
|
-
case "image": {
|
|
1243
|
-
const src = node.attrs?.src ?? "";
|
|
1244
|
-
const alt = node.attrs?.alt ?? "";
|
|
1245
|
-
return `${indent}`;
|
|
1246
|
-
}
|
|
1247
|
-
case "youtube": {
|
|
1248
|
-
const src = node.attrs?.src ?? "";
|
|
1249
|
-
return `${indent}[YouTube](${src})`;
|
|
1250
|
-
}
|
|
1251
|
-
default:
|
|
1252
|
-
if (node.content) {
|
|
1253
|
-
return renderChildren(node.content, indent);
|
|
1254
|
-
}
|
|
1255
|
-
return "";
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
function renderChildren(nodes, indent = "") {
|
|
1259
|
-
if (!nodes) return "";
|
|
1260
|
-
return nodes.map((node) => renderNode(node, indent)).join("\n\n");
|
|
1261
|
-
}
|
|
1262
|
-
function tiptapJsonToMarkdown(json) {
|
|
1263
|
-
const doc = typeof json === "string" ? JSON.parse(json) : json;
|
|
1264
|
-
return renderNode(doc).trim();
|
|
1265
|
-
}
|
|
1266
1143
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1267
1144
|
0 && (module.exports = {
|
|
1268
1145
|
MATH_MARKDOWN_RULES_APPENDIX,
|
|
1269
1146
|
MarkdownRenderer,
|
|
1270
1147
|
normalizeMathMarkdownDelimiters,
|
|
1271
|
-
renderMarkdownToHtml
|
|
1272
|
-
tiptapJsonToMarkdown
|
|
1148
|
+
renderMarkdownToHtml
|
|
1273
1149
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -19,30 +19,4 @@ declare const MarkdownRenderer: ({ markdown, className, onRunCode, executableLan
|
|
|
19
19
|
declare function normalizeMathMarkdownDelimiters(markdown: string): string;
|
|
20
20
|
declare const MATH_MARKDOWN_RULES_APPENDIX = "Math formatting rules (must follow):\n- Inline math: use single-dollar delimiters like $...$.\n- Display math: use $$ delimiters on their own lines with nothing else on those lines.\n- Do not use \\(...\\) or \\[...\\] delimiters.\n- Do not place display-math $$...$$ inside bullets or table cells; use inline $...$ there.\n- Escape non-math currency dollars as \\$.";
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
* Converts TipTap JSON (ProseMirror document model) to markdown string.
|
|
24
|
-
*
|
|
25
|
-
* Supports: paragraphs, headings (1-6), bold, italic, code, strike,
|
|
26
|
-
* links, images, bullet lists, ordered lists, blockquotes, code blocks,
|
|
27
|
-
* horizontal rules, hard breaks, and YouTube embeds.
|
|
28
|
-
*/
|
|
29
|
-
interface TipTapMark {
|
|
30
|
-
type: string;
|
|
31
|
-
attrs?: Record<string, unknown>;
|
|
32
|
-
}
|
|
33
|
-
interface TipTapNode {
|
|
34
|
-
type: string;
|
|
35
|
-
content?: TipTapNode[];
|
|
36
|
-
text?: string;
|
|
37
|
-
marks?: TipTapMark[];
|
|
38
|
-
attrs?: Record<string, unknown>;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Convert a TipTap JSON document to a markdown string.
|
|
42
|
-
*
|
|
43
|
-
* @param json - Either a TipTapNode object or a JSON string of one.
|
|
44
|
-
* @returns The markdown string representation.
|
|
45
|
-
*/
|
|
46
|
-
declare function tiptapJsonToMarkdown(json: TipTapNode | string): string;
|
|
47
|
-
|
|
48
|
-
export { type CodeExecutionResult, MATH_MARKDOWN_RULES_APPENDIX, MarkdownRenderer, type MarkdownRendererProps, type TipTapMark, type TipTapNode, normalizeMathMarkdownDelimiters, renderMarkdownToHtml, tiptapJsonToMarkdown };
|
|
22
|
+
export { type CodeExecutionResult, MATH_MARKDOWN_RULES_APPENDIX, MarkdownRenderer, type MarkdownRendererProps, normalizeMathMarkdownDelimiters, renderMarkdownToHtml };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,30 +19,4 @@ declare const MarkdownRenderer: ({ markdown, className, onRunCode, executableLan
|
|
|
19
19
|
declare function normalizeMathMarkdownDelimiters(markdown: string): string;
|
|
20
20
|
declare const MATH_MARKDOWN_RULES_APPENDIX = "Math formatting rules (must follow):\n- Inline math: use single-dollar delimiters like $...$.\n- Display math: use $$ delimiters on their own lines with nothing else on those lines.\n- Do not use \\(...\\) or \\[...\\] delimiters.\n- Do not place display-math $$...$$ inside bullets or table cells; use inline $...$ there.\n- Escape non-math currency dollars as \\$.";
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
* Converts TipTap JSON (ProseMirror document model) to markdown string.
|
|
24
|
-
*
|
|
25
|
-
* Supports: paragraphs, headings (1-6), bold, italic, code, strike,
|
|
26
|
-
* links, images, bullet lists, ordered lists, blockquotes, code blocks,
|
|
27
|
-
* horizontal rules, hard breaks, and YouTube embeds.
|
|
28
|
-
*/
|
|
29
|
-
interface TipTapMark {
|
|
30
|
-
type: string;
|
|
31
|
-
attrs?: Record<string, unknown>;
|
|
32
|
-
}
|
|
33
|
-
interface TipTapNode {
|
|
34
|
-
type: string;
|
|
35
|
-
content?: TipTapNode[];
|
|
36
|
-
text?: string;
|
|
37
|
-
marks?: TipTapMark[];
|
|
38
|
-
attrs?: Record<string, unknown>;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Convert a TipTap JSON document to a markdown string.
|
|
42
|
-
*
|
|
43
|
-
* @param json - Either a TipTapNode object or a JSON string of one.
|
|
44
|
-
* @returns The markdown string representation.
|
|
45
|
-
*/
|
|
46
|
-
declare function tiptapJsonToMarkdown(json: TipTapNode | string): string;
|
|
47
|
-
|
|
48
|
-
export { type CodeExecutionResult, MATH_MARKDOWN_RULES_APPENDIX, MarkdownRenderer, type MarkdownRendererProps, type TipTapMark, type TipTapNode, normalizeMathMarkdownDelimiters, renderMarkdownToHtml, tiptapJsonToMarkdown };
|
|
22
|
+
export { type CodeExecutionResult, MATH_MARKDOWN_RULES_APPENDIX, MarkdownRenderer, type MarkdownRendererProps, normalizeMathMarkdownDelimiters, renderMarkdownToHtml };
|
package/dist/index.js
CHANGED
|
@@ -894,7 +894,7 @@ function renderMarkdownToHtml(markdown, options) {
|
|
|
894
894
|
parts.push(`<p>${content}</p>`);
|
|
895
895
|
i++;
|
|
896
896
|
}
|
|
897
|
-
return `<div class="prose max-w-none">${parts.join("")}</div>`;
|
|
897
|
+
return `<style>.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before,.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after{content:none}</style><div class="prose max-w-none">${parts.join("")}</div>`;
|
|
898
898
|
}
|
|
899
899
|
var mermaidInstance = null;
|
|
900
900
|
var MarkdownRenderer = ({
|
|
@@ -1101,132 +1101,9 @@ var MarkdownRenderer = ({
|
|
|
1101
1101
|
return /* @__PURE__ */ jsx("div", { ref: containerRef, className, dangerouslySetInnerHTML: { __html: html } });
|
|
1102
1102
|
};
|
|
1103
1103
|
var markdown_renderer_default = MarkdownRenderer;
|
|
1104
|
-
|
|
1105
|
-
// src/tiptap-to-markdown.ts
|
|
1106
|
-
function renderMarks(text, marks) {
|
|
1107
|
-
if (!marks || marks.length === 0) return text;
|
|
1108
|
-
let result = text;
|
|
1109
|
-
for (const mark of marks) {
|
|
1110
|
-
switch (mark.type) {
|
|
1111
|
-
case "bold":
|
|
1112
|
-
result = `**${result}**`;
|
|
1113
|
-
break;
|
|
1114
|
-
case "italic":
|
|
1115
|
-
result = `*${result}*`;
|
|
1116
|
-
break;
|
|
1117
|
-
case "strike":
|
|
1118
|
-
result = `~~${result}~~`;
|
|
1119
|
-
break;
|
|
1120
|
-
case "code":
|
|
1121
|
-
result = `\`${result}\``;
|
|
1122
|
-
break;
|
|
1123
|
-
case "link": {
|
|
1124
|
-
const href = mark.attrs?.href ?? "";
|
|
1125
|
-
result = `[${result}](${href})`;
|
|
1126
|
-
break;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
return result;
|
|
1131
|
-
}
|
|
1132
|
-
function renderInlineContent(nodes) {
|
|
1133
|
-
if (!nodes) return "";
|
|
1134
|
-
return nodes.map((node) => {
|
|
1135
|
-
if (node.type === "text") {
|
|
1136
|
-
return renderMarks(node.text ?? "", node.marks);
|
|
1137
|
-
}
|
|
1138
|
-
if (node.type === "hardBreak") {
|
|
1139
|
-
return " \n";
|
|
1140
|
-
}
|
|
1141
|
-
if (node.type === "image") {
|
|
1142
|
-
const src = node.attrs?.src ?? "";
|
|
1143
|
-
const alt = node.attrs?.alt ?? "";
|
|
1144
|
-
return ``;
|
|
1145
|
-
}
|
|
1146
|
-
return "";
|
|
1147
|
-
}).join("");
|
|
1148
|
-
}
|
|
1149
|
-
function renderNode(node, indent = "", listCounter) {
|
|
1150
|
-
switch (node.type) {
|
|
1151
|
-
case "doc":
|
|
1152
|
-
return renderChildren(node.content, indent);
|
|
1153
|
-
case "paragraph":
|
|
1154
|
-
return `${indent}${renderInlineContent(node.content)}`;
|
|
1155
|
-
case "heading": {
|
|
1156
|
-
const level = node.attrs?.level ?? 1;
|
|
1157
|
-
const prefix = "#".repeat(level);
|
|
1158
|
-
return `${prefix} ${renderInlineContent(node.content)}`;
|
|
1159
|
-
}
|
|
1160
|
-
case "bulletList":
|
|
1161
|
-
return (node.content ?? []).map((item) => renderNode(item, indent, void 0)).join("\n");
|
|
1162
|
-
case "orderedList": {
|
|
1163
|
-
const counter = { n: node.attrs?.start ?? 1 };
|
|
1164
|
-
return (node.content ?? []).map((item) => {
|
|
1165
|
-
const result = renderNode(item, indent, counter);
|
|
1166
|
-
counter.n++;
|
|
1167
|
-
return result;
|
|
1168
|
-
}).join("\n");
|
|
1169
|
-
}
|
|
1170
|
-
case "listItem": {
|
|
1171
|
-
const prefix = listCounter ? `${indent}${listCounter.n}. ` : `${indent}- `;
|
|
1172
|
-
const children = node.content ?? [];
|
|
1173
|
-
const parts = [];
|
|
1174
|
-
for (let i = 0; i < children.length; i++) {
|
|
1175
|
-
const child = children[i];
|
|
1176
|
-
if (i === 0 && child.type === "paragraph") {
|
|
1177
|
-
parts.push(`${prefix}${renderInlineContent(child.content)}`);
|
|
1178
|
-
} else if (child.type === "bulletList" || child.type === "orderedList") {
|
|
1179
|
-
parts.push(renderNode(child, indent + " "));
|
|
1180
|
-
} else if (child.type === "paragraph") {
|
|
1181
|
-
parts.push(`${indent} ${renderInlineContent(child.content)}`);
|
|
1182
|
-
} else {
|
|
1183
|
-
parts.push(renderNode(child, indent + " "));
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
return parts.join("\n");
|
|
1187
|
-
}
|
|
1188
|
-
case "blockquote":
|
|
1189
|
-
return (node.content ?? []).map((child) => {
|
|
1190
|
-
const line = renderNode(child, indent);
|
|
1191
|
-
return `${indent}> ${line.replace(new RegExp(`^${indent}`), "")}`;
|
|
1192
|
-
}).join("\n");
|
|
1193
|
-
case "codeBlock": {
|
|
1194
|
-
const lang = node.attrs?.language ?? "";
|
|
1195
|
-
const code = (node.content ?? []).map((c) => c.text ?? "").join("");
|
|
1196
|
-
return `${indent}\`\`\`${lang}
|
|
1197
|
-
${code}
|
|
1198
|
-
${indent}\`\`\``;
|
|
1199
|
-
}
|
|
1200
|
-
case "horizontalRule":
|
|
1201
|
-
return `${indent}---`;
|
|
1202
|
-
case "image": {
|
|
1203
|
-
const src = node.attrs?.src ?? "";
|
|
1204
|
-
const alt = node.attrs?.alt ?? "";
|
|
1205
|
-
return `${indent}`;
|
|
1206
|
-
}
|
|
1207
|
-
case "youtube": {
|
|
1208
|
-
const src = node.attrs?.src ?? "";
|
|
1209
|
-
return `${indent}[YouTube](${src})`;
|
|
1210
|
-
}
|
|
1211
|
-
default:
|
|
1212
|
-
if (node.content) {
|
|
1213
|
-
return renderChildren(node.content, indent);
|
|
1214
|
-
}
|
|
1215
|
-
return "";
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
function renderChildren(nodes, indent = "") {
|
|
1219
|
-
if (!nodes) return "";
|
|
1220
|
-
return nodes.map((node) => renderNode(node, indent)).join("\n\n");
|
|
1221
|
-
}
|
|
1222
|
-
function tiptapJsonToMarkdown(json) {
|
|
1223
|
-
const doc = typeof json === "string" ? JSON.parse(json) : json;
|
|
1224
|
-
return renderNode(doc).trim();
|
|
1225
|
-
}
|
|
1226
1104
|
export {
|
|
1227
1105
|
MATH_MARKDOWN_RULES_APPENDIX,
|
|
1228
1106
|
markdown_renderer_default as MarkdownRenderer,
|
|
1229
1107
|
normalizeMathMarkdownDelimiters,
|
|
1230
|
-
renderMarkdownToHtml
|
|
1231
|
-
tiptapJsonToMarkdown
|
|
1108
|
+
renderMarkdownToHtml
|
|
1232
1109
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@affanhamid/markdown-renderer",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "https://github.com/affanhamid/markdown-renderer"
|
|
7
|
+
},
|
|
4
8
|
"description": "Custom markdown renderer with KaTeX support",
|
|
5
9
|
"type": "module",
|
|
6
10
|
"main": "dist/index.cjs",
|